#region Tokens
EOF
	: "\0 EOF"
	;
EMPTY:
	: "\0 EMPTY"
	;
NONE
	: "\0 NONE"
	;
ERROR
	: "\0 ERROR"
	;
ABSTRACT
	: "abstract"
	;
AS
	: "as"
	;
ADD
	: "add"
	;
ASSEMBLY
	: "assembly"
	;
BASE
	: "base"
	;
BOOL
	: "bool"
	;
BREAK
	: "break"
	;
BYTE
	: "byte"
	;
CASE
	: "case"
	;
CATCH
	: "catch"
	;
CHAR
	: "char"
	;
CHECKED
	: "checked"
	;
CLASS
	: "class"
	;
CONST
	: "const"
	;
CONTINUE
	: "continue"
	;
DECIMAL
	: "decimal"
	;
DEFAULT
	: "default"
	;
DELEGATE
	: "delegate"
	;
DO
	: "do"
	;
DOUBLE
	: "double"
	;
ELSE
	: "else"
	;
ENUM
	: "enum"
	;
EVENT
	: "event"
	;
EXPLICIT
	: "explicit"
	;
EXTERN
	: "extern"
	;
FALSE
	: "false"
	;
FINALLY
	: "finally"
	;
FIXED
	: "fixed"
	;
FLOAT
	: "float"
	;
FOR	
	: "for"
	;
FOREACH
	: "foreach"
	;
GOTO
	: "goto"
	;
IF	
	: "if"
	;
IMPLICIT
	: "implicit"
	;
IN	
	: "in"
	;
INT	
	: "int"
	;
INTERFACE
	: "interface"
	;
INTERNAL
	: "internal"
	;
IS	
	: "is"
	;
LOCK
	: "lock"
	;
LONG
	: "long"
	;
NAMESPACE
	: "namespace"
	;
NEW	
	: "new"
	;
NULL
	: "null"
	;
OBJECT
	: "object"
	;
OPERATOR
	: "operator"
	;
OUT	
	: "out"
	;
OVERRIDE
	: "override"
	;
PARAMS
	: "params"
	;
PRIVATE
	: "private"
	;
PROTECTED
	: "protected"
	;
PUBLIC
	: "public"
	;
READONLY
	: "readonly"
	;
REF	
	: "ref"
	;
RETURN
	: "return"
	;
REMOVE
	: "remove"
	;
SBYTE
	: "sbyte"
	;
SEALED
	: "sealed"
	;
SHORT
	: "short"
	;
SIZEOF
	: "sizeof"
	;
STACKALLOC
	: "stackalloc"
	;
STATIC
	: "static"
	;
STRING
	: "string"
	;
STRUCT
	: "struct"
	;
SWITCH
	: "switch"
	;
THIS
	: "this"
	;
THROW
	: "throw"
	;
TRUE
	: "true"
	;
TRY	
	: "try"
	;
TYPEOF
	: "typeof"
	;
UINT
	: "uint"
	;
ULONG
	: "ulong"
	;
UNCHECKED
	: "unchecked"
	;
UNSAFE
	: "unsafe"
	;
USHORT
	: "ushort"
	;
USING
	: "using"
	;
VIRTUAL
	: "virtual"
	;
VOID
	: "void"
	;
VOLATILE
	: "volatile"
	;
WHILE
	: "while"
	;
GET 
	: "get"
	;
SET 
	: "set"
	;
OPEN_BRACE
	: "{"
	;
CLOSE_BRACE
	: "}"
	;
OPEN_BRACKET
	: "["
	;
CLOSE_BRACKET
	: "]"
	;
OPEN_PARENS
	: "("
	;
CLOSE_PARENS
	: ")"
	;
DOT
	:"."
	;
COMMA
	: ","
	;
COLON
	: ":"
	;
SEMICOLON
	: ";"
	;
TILDE
	: "~"
	;
PLUS
	: "+"
	;
MINUS
	: "-"
	;
BANG
	: "!"
	;
ASSIGN
	: "="
	;
OP_LT
	: "<"
	;
OP_GT
	: ">"
	;
BITWISE_AND
	: "&"
	;
BITWISE_OR
	: "|"
	;
STAR
	: "*"
	;
PERCENT
	: "%"
	;
DIV 
	: "/"
	;
CARRET
	: "^"
	;
INTERR
	: "?"
	;
OP_INC
	: "++"
	;
OP_DEC
	: "--"
	;
OP_SHIFT_LEFT
	: "<<"
	;
OP_SHIFT_RIGHT
	: ">>"
	;
OP_LE
	: "<="
	;
OP_GE
	: ">="
	;
OP_EQ
	: "=="
	;
OP_NE
	: "!="
	;
OP_AND
	: "&&"
	;
OP_OR
	: "||"
	;
OP_MULT_ASSIGN
	: "*="
	;
OP_DIV_ASSIGN
	: "/="
	;
OP_MOD_ASSIGN
	: "%="
	;
OP_ADD_ASSIGN
	: "+="
	;
OP_SUB_ASSIGN
	: "-="
	;
OP_SHIFT_LEFT_ASSIGN
	: "<<="
	;
OP_SHIFT_RIGHT_ASSIGN
	: ">>="
	;
OP_AND_ASSIGN
	: "&="
	;
OP_XOR_ASSIGN
	: "^="
	;
OP_OR_ASSIGN
	: "|="
	;
OP_PTR
	: "->"
	;

LITERAL_INTEGER
	: "\0 int_literal"
	;
LITERAL_FLOAT
	: "\0 float_literal"
	;
LITERAL_DOUBLE
	: "\0 double_literal"
	;
LITERAL_DECIMAL
	: "\0 decimal_literal"
	;
LITERAL_CHARACTER
	: "\0 character_literal"
	;
LITERAL_STRING
	: "\0 string_literal"
	;

IDENTIFIER
	: "\0 IDENTIFIER"
	;
CLOSE_PARENS_CAST
  : "\0 CLOSE_PARENS_CAST"
  ;
CLOSE_PARENS_NO_CAST
  : "\0 CLOSE_PARENS_NO_CAST"
  ;
CLOSE_PARENS_OPEN_PARENS
  : "\0 CLOSE_PARENS_OPEN_PARENS"
  ;
CLOSE_PARENS_MINUS
  : "\0 CLOSE_PARENS_MINUS"
  ;
#endregion
#region Defs
compilation_unit
  : outer_declarations opt_EOF
  | outer_declarations global_attributes opt_EOF
  | global_attributes opt_EOF
	| opt_EOF
  ;
	
opt_EOF
	: EMPTY
	| EOF
	;

outer_declarations
  : outer_declaration
  | outer_declarations outer_declaration
  ;
 
outer_declaration
  : using_directive
  | namespace_member_declaration
  ;
  
using_directives
	: using_directive 
	| using_directives using_directive
	;

using_directive
	: using_alias_directive
	| using_namespace_directive
	;

using_alias_directive
	: USING IDENTIFIER ASSIGN namespace_or_type_name SEMICOLON
	;

using_namespace_directive
	: USING namespace_name SEMICOLON 
	;

namespace_declaration
	: opt_attributes NAMESPACE namespace_or_type_name namespace_body opt_semicolon
	;

opt_semicolon
	: EMPTY
	| SEMICOLON
	;

opt_comma
	: EMPTY
	| COMMA
	;

namespace_name
	: namespace_or_type_name
	;

namespace_body
	: OPEN_BRACE opt_using_directives opt_namespace_member_declarations CLOSE_BRACE
	;

opt_using_directives
	: EMPTY
	| using_directives
	;

opt_namespace_member_declarations
	: EMPTY
	| namespace_member_declarations
	;

namespace_member_declarations
	: namespace_member_declaration
	| namespace_member_declarations namespace_member_declaration
	;

namespace_member_declaration
	: type_declaration
	| namespace_declaration
	;

type_declaration
	: class_declaration		
	| struct_declaration		
	| interface_declaration		
	| enum_declaration		
	| delegate_declaration
	;

global_attributes
	: attribute_sections
  ;

opt_attributes
	: EMPTY 
	| attribute_sections
  ;

attribute_sections
	: attribute_section
	| attribute_sections attribute_section
	;

attribute_section
	: OPEN_BRACKET attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET
  | OPEN_BRACKET attribute_list opt_comma CLOSE_BRACKET
	;
 
attribute_target_specifier
	: attribute_target COLON
	;

attribute_target
	: IDENTIFIER
  | EVENT
  | RETURN
	;

attribute_list
	: attribute
	| attribute_list COMMA attribute
	;

attribute
	: attribute_name
	;

attribute_name
	: type_name
	;

opt_attribute_arguments
	: EMPTY
	| OPEN_PARENS attribute_arguments CLOSE_PARENS
	;


attribute_arguments
	: opt_positional_argument_list
  | positional_argument_list COMMA named_argument_list
  | named_argument_list
  ;


opt_positional_argument_list
	: EMPTY
	| positional_argument_list
	;

positional_argument_list
	: expression
  | positional_argument_list COMMA expression
  ;

named_argument_list
	: named_argument
  | named_argument_list COMMA named_argument
  ;

named_argument
	: IDENTIFIER ASSIGN expression
	;

		  
class_body
	:  OPEN_BRACE opt_class_member_declarations CLOSE_BRACE
	;

opt_class_member_declarations
	: EMPTY
	| class_member_declarations
	;

class_member_declarations
	: class_member_declaration
	| class_member_declarations 
	  class_member_declaration
	;

class_member_declaration
	: constant_declaration
	| field_declaration
	| method_declaration
	| property_declaration
	| event_declaration
	| indexer_declaration
	| operator_declaration
	| constructor_declaration
	| destructor_declaration
	| type_declaration
	;

struct_declaration
	: opt_attributes
	  opt_modifiers
	  STRUCT IDENTIFIER
	  opt_class_base
	  struct_body
	  opt_semicolon
	;

struct_body
	: OPEN_BRACE opt_struct_member_declarations CLOSE_BRACE
	;

opt_struct_member_declarations
	: EMPTY
	| struct_member_declarations
	;

struct_member_declarations
	: struct_member_declaration
	| struct_member_declarations struct_member_declaration
	;

struct_member_declaration
	: constant_declaration
	| field_declaration
	| method_declaration
	| property_declaration
	| event_declaration
	| indexer_declaration
	| operator_declaration
	| constructor_declaration
	| type_declaration
	| destructor_declaration 
	;

constant_declaration
	: opt_attributes 
	  opt_modifiers
	  CONST
	  type
	  constant_declarators
	  SEMICOLON
	;

constant_declarators
	: constant_declarator 
	| constant_declarators COMMA constant_declarator
	;

constant_declarator
	: IDENTIFIER ASSIGN constant_expression
	| IDENTIFIER
	;

field_declaration
	: opt_attributes
	  opt_modifiers
	  type 
	  variable_declarators
	  SEMICOLON
	;

variable_declarators
	: variable_declarator 
	| variable_declarators COMMA variable_declarator
	;

variable_declarator
	: IDENTIFIER ASSIGN variable_initializer
	| IDENTIFIER
	;

variable_initializer
	: expression
	| array_initializer
	| STACKALLOC type OPEN_BRACKET expression CLOSE_BRACKET
	;

method_declaration
	: method_header 
	  method_body
	;

opt_error_modifier
	: EMPTY
	| modifiers 
	;

method_header
	: opt_attributes opt_modifiers type member_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
	| opt_attributes opt_modifiers VOID member_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
	| opt_attributes opt_modifiers type modifiers member_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
	;

method_body
	: block
	| SEMICOLON
	;

opt_formal_parameter_list
	: EMPTY
	| formal_parameter_list
	;

formal_parameter_list
	: fixed_parameters		
	| fixed_parameters COMMA parameter_array
	| fixed_parameters COMMA ARGLIST
	| parameter_array 
	| ARGLIST
	;

fixed_parameters
	: fixed_parameter	
	| fixed_parameters COMMA fixed_parameter
	;

fixed_parameter
	: opt_attributes opt_parameter_modifier type IDENTIFIER
	;

opt_parameter_modifier
	: EMPTY
	| parameter_modifier
	;

parameter_modifier
	: REF
	| OUT
	;

parameter_array
	: opt_attributes PARAMS type IDENTIFIER
	;

member_name 
	: namespace_or_type_name
	;

property_declaration
	: opt_attributes opt_modifiers type member_name OPEN_BRACE accessor_declarations CLOSE_BRACE
	;

accessor_declarations
	: get_accessor_declaration opt_set_accessor_declaration
	| set_accessor_declaration opt_get_accessor_declaration
	;

opt_get_accessor_declaration
	: EMPTY
	| get_accessor_declaration
	;

opt_set_accessor_declaration
	: EMPTY
	| set_accessor_declaration
	;

get_accessor_declaration
	: opt_attributes GET accessor_body
	;

set_accessor_declaration
	: opt_attributes SET accessor_body
	;

accessor_body
	: block 
	| SEMICOLON
	;

interface_declaration
	: opt_attributes
	  opt_modifiers
	  INTERFACE IDENTIFIER opt_class_base
	  interface_body opt_semicolon
	;

interface_body
	: OPEN_BRACE
	  opt_interface_member_declarations
	  CLOSE_BRACE
	;

opt_interface_member_declarations
	: EMPTY
	| interface_member_declarations
	;

interface_member_declarations
	: interface_member_declaration
	| interface_member_declarations interface_member_declaration
	;

interface_member_declaration
	: interface_method_declaration		
	| interface_property_declaration	
	| interface_event_declaration 
	| interface_indexer_declaration
	;

opt_new
	: opt_modifiers 
	;

interface_method_declaration
	: opt_attributes opt_new type IDENTIFIER 
	  OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
	  SEMICOLON
	| opt_attributes opt_new VOID IDENTIFIER 
	  OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS
	  SEMICOLON
	;

interface_property_declaration
	: opt_attributes opt_new type IDENTIFIER OPEN_BRACE interface_accessors CLOSE_BRACE
	;

interface_accessors
	: opt_attributes GET SEMICOLON
	| opt_attributes SET SEMICOLON
	| opt_attributes GET SEMICOLON opt_attributes SET SEMICOLON 
	| opt_attributes SET SEMICOLON opt_attributes GET SEMICOLON
	;

interface_event_declaration
	: opt_attributes opt_new EVENT type IDENTIFIER SEMICOLON
	| opt_attributes opt_new EVENT type IDENTIFIER ASSIGN
	| opt_attributes opt_new EVENT type IDENTIFIER OPEN_BRACE event_accessor_declarations CLOSE_BRACE
	;

interface_indexer_declaration 
	: opt_attributes opt_new type THIS OPEN_BRACKET formal_parameter_list CLOSE_BRACKET OPEN_BRACE interface_accessors CLOSE_BRACE
	;

operator_declaration
	: opt_attributes opt_modifiers operator_declarator operator_body
	;

operator_body 
	: block
	| SEMICOLON
	; 
operator_declarator
	: type OPERATOR overloadable_operator OPEN_PARENS type IDENTIFIER CLOSE_PARENS
	| type OPERATOR overloadable_operator OPEN_PARENS type IDENTIFIER COMMA	type IDENTIFIER CLOSE_PARENS
	| conversion_operator_declarator
	;

overloadable_operator
// Unary operators:
	: BANG
  | TILDE
  | OP_INC
  | OP_DEC
  | TRUE
  | FALSE
// Unary and binary:
  | PLUS
  | MINUS
// Binary:
  | STAR
  | DIV
  | PERCENT
  | BITWISE_AND
  | BITWISE_OR
  | CARRET
  | OP_SHIFT_LEFT 
  | OP_SHIFT_RIGHT 
  | OP_EQ 
  | OP_NE 
  | OP_GT 
  | OP_LT 
  | OP_GE 
  | OP_LE
	;

conversion_operator_declarator
	: IMPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
	| EXPLICIT OPERATOR type OPEN_PARENS type IDENTIFIER CLOSE_PARENS
	;

constructor_declaration
	: opt_attributes opt_modifiers constructor_declarator constructor_body
	;

constructor_declarator
	: IDENTIFIER OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS 
	;

constructor_body
	: block
	| SEMICOLON
	;

opt_constructor_initializer
	: EMPTY
	| constructor_initializer
	;

constructor_initializer
	: COLON BASE OPEN_PARENS opt_argument_list CLOSE_PARENS
	| COLON THIS OPEN_PARENS opt_argument_list CLOSE_PARENS
	;

opt_finalizer
  : EMPTY
  | UNSAFE
	| EXTERN
  ;
        
destructor_declaration
	: opt_attributes opt_finalizer TILDE IDENTIFIER OPEN_PARENS CLOSE_PARENS block
	;

event_declaration
	: opt_attributes
	  opt_modifiers
	  EVENT type variable_declarators SEMICOLON
	| opt_attributes
	  opt_modifiers
	  EVENT type member_name
	  OPEN_BRACE
	  event_accessor_declarations
	  CLOSE_BRACE
	| opt_attributes opt_modifiers EVENT type member_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS block

	;

event_accessor_declarations
	: add_accessor_declaration remove_accessor_declaration
	| remove_accessor_declaration add_accessor_declaration
	| add_accessor_declaration 
	| remove_accessor_declaration
	;

add_accessor_declaration
	: opt_attributes ADD block
	;

remove_accessor_declaration
	: opt_attributes REMOVE block
	;

indexer_declaration
	: opt_attributes opt_modifiers indexer_declarator 
	  OPEN_BRACE accessor_declarations CLOSE_BRACE
	;

indexer_declarator
	: type THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
	| type namespace_or_type_name DOT THIS OPEN_BRACKET opt_formal_parameter_list CLOSE_BRACKET
	;

enum_declaration
	: opt_attributes
	  opt_modifiers
	  ENUM IDENTIFIER 
	  opt_enum_base
	  enum_body
	  opt_semicolon
	;

opt_enum_base
	: EMPTY
	| COLON type
	;

enum_body
	: OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE
	;

opt_enum_member_declarations
	: EMPTY
	| enum_member_declarations opt_comma
	;

enum_member_declarations
	: enum_member_declaration 
	| enum_member_declarations COMMA enum_member_declaration
	;

enum_member_declaration
	: opt_attributes IDENTIFIER 
	| opt_attributes IDENTIFIER ASSIGN expression
	;

delegate_declaration
	: opt_attributes
	  opt_modifiers
	  DELEGATE type	  
	  IDENTIFIER OPEN_PARENS 
	  opt_formal_parameter_list
	  CLOSE_PARENS 
	  SEMICOLON
	| opt_attributes
	  opt_modifiers
	  DELEGATE VOID	  
	  IDENTIFIER OPEN_PARENS 
	  opt_formal_parameter_list
	  CLOSE_PARENS 
	  SEMICOLON
	;

type_name
	: namespace_or_type_name
	;

namespace_or_type_name
	: IDENTIFIER
	| namespace_or_type_name DOT IDENTIFIER
	;

type
	: type_name
	| builtin_types
	| array_type
	| pointer_type	  
	;


pointer_type
	: type STAR
	| VOID STAR
	;

non_expression_type
	: builtin_types	
	| non_expression_type rank_specifier
	| non_expression_type STAR
	| expression rank_specifiers 
	| expression STAR 
	| multiplicative_expression STAR 
	;

type_list
	: type
	| type_list COMMA type
	;

builtin_types
	: OBJECT
	| STRING
	| BOOL
	| DECIMAL
	| FLOAT
	| DOUBLE
	| integral_type
	;

integral_type
	: SBYTE
	| BYTE
	| SHORT
	| USHORT
	| INT
	| UINT
	| LONG
	| ULONG
	| CHAR
	| VOID
	;

interface_type
	: type_name
	;

array_type
	: type rank_specifiers
	;

//
// Expressions, section 7.5
//
primary_expression
	: literal
	| IDENTIFIER
	| parenthesized_expression
	| member_access
	| invocation_expression
	| element_access
	| this_access
	| base_access
	| post_increment_expression
	| post_decrement_expression
	| new_expression
	| typeof_expression
	| sizeof_expression
	| checked_expression
	| unchecked_expression
	| pointer_member_access
	| anonymous_method_expression
	;

literal
	: boolean_literal
	| integer_literal
	| real_literal
	| LITERAL_CHARACTER
	| LITERAL_STRING
	| NULL
	;

real_literal
	: LITERAL_FLOAT
	| LITERAL_DOUBLE
	| LITERAL_DECIMAL
	;

integer_literal
	: LITERAL_INTEGER
	;

boolean_literal
	: TRUE
	| FALSE
	;

parenthesized_expression_0
	: OPEN_PARENS expression CLOSE_PARENS
	;

parenthesized_expression
	: parenthesized_expression_0 CLOSE_PARENS_NO_CAST
	| parenthesized_expression_0 CLOSE_PARENS_MINUS
	;

member_access
	: primary_expression DOT IDENTIFIER
	| predefined_type DOT IDENTIFIER
	;

predefined_type
	: builtin_types
	;

invocation_expression
	: primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
	| parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS OPEN_PARENS CLOSE_PARENS
	| parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS primary_expression
	;

opt_argument_list
	: EMPTY
	| argument_list
	;

argument_list
	: argument
	| argument_list COMMA argument
	;

argument
	: expression
	| REF variable_reference 
	| OUT variable_reference 
	| ARGLIST OPEN_PARENS argument_list CLOSE_PARENS
	| ARGLIST
	;

variable_reference
	: expression
	;

element_access
	: primary_expression OPEN_BRACKET expression_list CLOSE_BRACKET	
	| primary_expression rank_specifiers
	;

expression_list
	: expression
	| expression_list COMMA expression
	;

this_access
	: THIS
	;

base_access
	: BASE DOT IDENTIFIER
	| BASE OPEN_BRACKET expression_list CLOSE_BRACKET
	;

post_increment_expression
	: primary_expression OP_INC
	;

post_decrement_expression
	: primary_expression OP_DEC
	;

new_expression
	: object_or_delegate_creation_expression
	| array_creation_expression
	;

object_or_delegate_creation_expression
	: NEW type OPEN_PARENS opt_argument_list CLOSE_PARENS
	;

array_creation_expression
	: NEW type OPEN_BRACKET expression_list CLOSE_BRACKET 
	  opt_rank_specifier
	  opt_array_initializer
	| NEW type rank_specifiers array_initializer
	| NEW type error 
	;

opt_rank_specifier
	: EMPTY
	| rank_specifiers
	;

rank_specifiers
	: rank_specifier opt_rank_specifier
  ;

rank_specifier
	: OPEN_BRACKET opt_dim_separators CLOSE_BRACKET
	;

opt_dim_separators
	: EMPTY
	| dim_separators	  
	;

dim_separators
	: COMMA
	| dim_separators COMMA
	;

opt_array_initializer
	: EMPTY
  | array_initializer
	;

array_initializer
	: OPEN_BRACE CLOSE_BRACE
	| OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE
	;

variable_initializer_list
	: variable_initializer
	| variable_initializer_list COMMA variable_initializer
	;

typeof_expression
	: TYPEOF OPEN_PARENS VOID CLOSE_PARENS
	| TYPEOF OPEN_PARENS type CLOSE_PARENS
	;

sizeof_expression
	: SIZEOF OPEN_PARENS type CLOSE_PARENS
	;

checked_expression
	: CHECKED OPEN_PARENS expression CLOSE_PARENS
	;

unchecked_expression
	: UNCHECKED OPEN_PARENS expression CLOSE_PARENS
	;

pointer_member_access 
	: primary_expression OP_PTR IDENTIFIER
	;

anonymous_method_expression
	: DELEGATE opt_anonymous_method_signature
	;

opt_anonymous_method_signature
	: EMPTY
	| anonymous_method_signature
	;

anonymous_method_signature
	: OPEN_PARENS opt_anonymous_method_parameter_list CLOSE_PARENS 
	;

opt_anonymous_method_parameter_list
	: EMPTY
	| anonymous_method_parameter_list
  ;

anonymous_method_parameter_list
	: anonymous_method_parameter 
	| anonymous_method_parameter_list COMMA anonymous_method_parameter 
	; 

anonymous_method_parameter
	: opt_parameter_modifier type IDENTIFIER
	;

unary_expression
	: primary_expression
	| BANG prefixed_unary_expression
	| TILDE prefixed_unary_expression
	| cast_expression
	;

cast_list
	: parenthesized_expression_0 CLOSE_PARENS_CAST unary_expression
	| parenthesized_expression_0 CLOSE_PARENS_OPEN_PARENS cast_expression
	;

cast_expression
	: cast_list
	| OPEN_PARENS non_expression_type CLOSE_PARENS prefixed_unary_expression
	;

prefixed_unary_expression
	: unary_expression
	| PLUS prefixed_unary_expression
	| MINUS prefixed_unary_expression 
	| OP_INC prefixed_unary_expression 
	| OP_DEC prefixed_unary_expression 
	| STAR prefixed_unary_expression
	| BITWISE_AND prefixed_unary_expression
	;

pre_increment_expression
	: OP_INC prefixed_unary_expression 
	;

pre_decrement_expression
	: OP_DEC prefixed_unary_expression 
	;

multiplicative_expression
	: prefixed_unary_expression
	| multiplicative_expression STAR prefixed_unary_expression
	| multiplicative_expression DIV prefixed_unary_expression
	| multiplicative_expression PERCENT prefixed_unary_expression 
	;

additive_expression
	: multiplicative_expression
	| additive_expression PLUS multiplicative_expression 
	| additive_expression MINUS multiplicative_expression
	;

shift_expression
	: additive_expression
	| shift_expression OP_SHIFT_LEFT additive_expression
	| shift_expression OP_SHIFT_RIGHT additive_expression
	; 

relational_expression
	: shift_expression
	| relational_expression OP_LT shift_expression
	| relational_expression OP_GT shift_expression
	| relational_expression OP_LE shift_expression
	| relational_expression OP_GE shift_expression
	| relational_expression IS type
	| relational_expression AS type
	;

equality_expression
	: relational_expression
	| equality_expression OP_EQ relational_expression
	| equality_expression OP_NE relational_expression
	; 

and_expression
	: equality_expression
	| and_expression BITWISE_AND equality_expression
	;

exclusive_or_expression
	: and_expression
	| exclusive_or_expression CARRET and_expression
	;

inclusive_or_expression
	: exclusive_or_expression
	| inclusive_or_expression BITWISE_OR exclusive_or_expression
	;

conditional_and_expression
	: inclusive_or_expression
	| conditional_and_expression OP_AND inclusive_or_expression
	;

conditional_or_expression
	: conditional_and_expression
	| conditional_or_expression OP_OR conditional_and_expression
	;

conditional_expression
	: conditional_or_expression
	| conditional_or_expression INTERR expression COLON expression 
	;

assignment_expression
	: prefixed_unary_expression ASSIGN expression
	| prefixed_unary_expression OP_MULT_ASSIGN expression
	| prefixed_unary_expression OP_DIV_ASSIGN expression
	| prefixed_unary_expression OP_MOD_ASSIGN expression
	| prefixed_unary_expression OP_ADD_ASSIGN expression
	| prefixed_unary_expression OP_SUB_ASSIGN expression
	| prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression
	| prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression
	| prefixed_unary_expression OP_AND_ASSIGN expression
	| prefixed_unary_expression OP_OR_ASSIGN expression
	| prefixed_unary_expression OP_XOR_ASSIGN expression
	;

expression
	: conditional_expression
	| assignment_expression
	;

constant_expression
	: expression
	;

boolean_expression
	: expression
	;

class_declaration
	: opt_attributes opt_modifiers CLASS IDENTIFIER opt_class_base class_body opt_semicolon 
	;	

opt_modifiers
	: EMPTY
	| modifiers
	;

modifiers
	: modifier
	| modifiers modifier
  ;

modifier
	: NEW
	| PUBLIC
	| PROTECTED
	| INTERNAL
	| PRIVATE
	| ABSTRACT
	| SEALED
	| STATIC
	| READONLY
	| VIRTUAL
	| OVERRIDE
	| EXTERN
	| VOLATILE
	| UNSAFE
	;

opt_class_base
	: EMPTY
	| class_base
	;

class_base
	: COLON type_list
	;
    
block
	: OPEN_BRACE opt_statement_list CLOSE_BRACE 

	;

opt_statement_list
	: EMPTY
	| statement_list 
	;

statement_list
	: statement
	| statement_list statement
	;

statement
	: declaration_statement
	| valid_declaration_statement
	| labeled_statement
	;

valid_declaration_statement
	: block
	| empty_statement
  | expression_statement
	| selection_statement
	| iteration_statement
	| jump_statement		  
	| try_statement
	| checked_statement
	| unchecked_statement
	| lock_statement
	| using_statement
	| unsafe_statement
	| fixed_statement
	;

embedded_statement
	: valid_declaration_statement
	| declaration_statement
	| labeled_statement
	;

empty_statement
	: SEMICOLON
	;

labeled_statement
	: IDENTIFIER COLON statement
	;

declaration_statement
	: local_variable_declaration SEMICOLON
	| local_constant_declaration SEMICOLON
	;

local_variable_type
	: primary_expression opt_rank_specifier
	| builtin_types opt_rank_specifier
  ;

local_variable_pointer_type
	: primary_expression STAR
  | builtin_types STAR
  | VOID STAR
	| local_variable_pointer_type STAR
  ;

local_variable_declaration
	: local_variable_type variable_declarators
  | local_variable_pointer_type opt_rank_specifier variable_declarators
 	;

local_constant_declaration
	: CONST local_variable_type constant_declarators
	;

expression_statement
	: statement_expression SEMICOLON
	;

statement_expression
	: invocation_expression
	| object_creation_expression
	| assignment_expression	
	| post_increment_expression
	| post_decrement_expression	
	| pre_increment_expression
	| pre_decrement_expression
	;

object_creation_expression
	: object_or_delegate_creation_expression
	;

selection_statement
	: if_statement
	| switch_statement
	; 

if_statement
	: if_statement_open if_statement_rest
	;

if_statement_open
	: IF OPEN_PARENS 
	;

if_statement_rest
	: boolean_expression CLOSE_PARENS 
	  embedded_statement
	| boolean_expression CLOSE_PARENS
	  embedded_statement ELSE embedded_statement
	;

switch_statement
	: SWITCH OPEN_PARENS expression CLOSE_PARENS switch_block
	;

switch_block
	: OPEN_BRACE
	  opt_switch_sections
	  CLOSE_BRACE
	;

opt_switch_sections
	: EMPTY
	| switch_sections
	;

switch_sections
	: switch_section 
	| switch_sections switch_section
	;

switch_section
	: switch_labels
 	  statement_list 
	;

switch_labels
	: switch_label 
	| switch_labels switch_label 
	;

switch_label
	: CASE constant_expression COLON
	| DEFAULT COLON
	;

iteration_statement
	: while_statement
	| do_statement
	| for_statement
	| foreach_statement
	;

while_statement
	: WHILE OPEN_PARENS boolean_expression CLOSE_PARENS embedded_statement
	;

do_statement
	: DO embedded_statement 
	  WHILE OPEN_PARENS boolean_expression CLOSE_PARENS SEMICOLON
	;

for_statement
	: FOR OPEN_PARENS 
	  opt_for_initializer SEMICOLON
	  opt_for_condition SEMICOLON
	  opt_for_iterator CLOSE_PARENS 
	  embedded_statement
	;

opt_for_initializer
	: EMPTY
	| for_initializer	
	;

for_initializer
	: local_variable_declaration
	| statement_expression_list
	;

opt_for_condition
	: EMPTY
	| boolean_expression
	;

opt_for_iterator
	: EMPTY
	| for_iterator
	;

for_iterator
	: statement_expression_list
	;

statement_expression_list
	: statement_expression	
	| statement_expression_list COMMA statement_expression
	;

foreach_statement
	: FOREACH OPEN_PARENS type IDENTIFIER IN  expression CLOSE_PARENS  embedded_statement 
	;

jump_statement
	: break_statement
	| continue_statement
	| goto_statement
	| return_statement
	| throw_statement
	| yield_statement
	;

break_statement
	: BREAK SEMICOLON
	;

continue_statement
	: CONTINUE SEMICOLON
	;

goto_statement
	: GOTO IDENTIFIER SEMICOLON 
	| GOTO CASE constant_expression SEMICOLON
	| GOTO DEFAULT SEMICOLON 
	; 

return_statement
	: RETURN opt_expression SEMICOLON
	;

throw_statement
	: THROW opt_expression SEMICOLON
	;

yield_statement 
	: IDENTIFIER RETURN expression SEMICOLON
	| IDENTIFIER BREAK SEMICOLON
	;

opt_expression
	: EMPTY
	| expression
	;

try_statement
	: TRY block catch_clauses 
	| TRY block opt_catch_clauses FINALLY block
	| TRY block error 
	;

opt_catch_clauses
	: EMPTY
  | catch_clauses
	;

catch_clauses
	: catch_clause 
	| catch_clauses catch_clause
	;

opt_identifier
	: EMPTY
	| IDENTIFIER
	;

catch_clause 
	: CATCH opt_catch_args  block
  ;

opt_catch_args
	: EMPTY
  | catch_args
	;	  

catch_args 
  : OPEN_PARENS type opt_identifier CLOSE_PARENS 
  ;

checked_statement
	: CHECKED block
	;

unchecked_statement
	: UNCHECKED block
	;

unsafe_statement
	: UNSAFE block	
  ;

fixed_statement
	: FIXED OPEN_PARENS 
	  type fixed_pointer_declarators 
	  CLOSE_PARENS embedded_statement 
	;

fixed_pointer_declarators
	: fixed_pointer_declarator
  | fixed_pointer_declarators COMMA fixed_pointer_declarator
	;

fixed_pointer_declarator
	: IDENTIFIER ASSIGN expression
	| IDENTIFIER
	;

lock_statement
	: LOCK OPEN_PARENS expression CLOSE_PARENS embedded_statement
	;

using_statement
	: USING OPEN_PARENS resource_acquisition CLOSE_PARENS embedded_statement
	; 

resource_acquisition
	: local_variable_declaration
	| expression
	;
#endregion